

class Local_Search():
    def __init__(self):
        self.solution = None
        self.neighbors = []
        self.best_neighbor = None
        self.best_neighbor_val = -1
        self.replace = True
        pass

    def search_(self,stop_func,*args,**kwargs):
        self.init_solution()
        for i in stop_func(*args,**kwargs):
            if i is False: break
            self.find_neighbors()
            self.pick_solution()
            self.update_solution()
        return self.solution

    def init_solution(self):
        self.solution = 4

    def find_neighbors(self):
        self.neighbors = set([])
        if self.solution > 1:
            self.neighbors.add(self.solution-1)
        if self.solution < 10:
            self.neighbors.add(self.solution+1)
        self.neighbors = list(self.neighbors)

    def pick_solution(self):
        self.best_neighbor_val = -1
        self.best_neighbor = None
        for one in self.neighbors:
            neighbor = self.eval_solution(one)
            if neighbor > self.best_neighbor_val:
                self.best_neighbor_val = neighbor
                self.best_neighbor = neighbor

    def update_solution(self):
        self.replace = False
        if self.best_neighbor is not None:
            if self.best_neighbor_val > self.eval_solution(self.solution):
                self.solution = self.best_neighbor
                self.replace = True

    def eval_solution(self,one):
        return one

    def stop_func_simple(self,num):
        for i in range(num):
            if self.replace is True:
                yield True
            else:
                yield False
        yield False

    def search(self,num):
        self.search_(self.stop_func_simple,num=num)

if __name__ == "__main__":
    a = Local_Search()
    a.search(100)
    print("solution: %s" % str(a.solution))
